﻿namespace MDXStudio.Tracing
{
    using Microsoft.AnalysisServices;
    using System;
    using System.Reflection;
    using System.Runtime.CompilerServices;
    using System.Windows.Forms;

    internal class Tracer
    {
        private readonly ListView mListView;
        private Server mServer;
        private TracerSetting mSetting;
        private eTracerState mState;

        public event EventHandler StateChanged;

        public Tracer(ListView pListView)
        {
            this.mListView = pListView;
            this.mSetting = TracerSetting.GetDefaultSetting();
            this.InitListView();
            this.mState = eTracerState.Disconnected;
        }

        private void AddTraceToListView(TraceEventArgs pArgs)
        {
            if (this.mListView.InvokeRequired)
            {
                this.mListView.Invoke(new AddTraceToListViewDelegate(this.AddTraceToListView), new object[] { pArgs });
            }
            else
            {
                TracerEvent event2 = new TracerEvent(pArgs);
                System.Type type = typeof(TracerEvent);
                ListViewItem item = null;
                string[] items = new string[this.mSetting.PropertyList.Count - 1];
                for (int i = 0; i < this.mSetting.PropertyList.Count; i++)
                {
                    PropertyInfo property = type.GetProperty(this.mSetting.PropertyList[i]);
                    object obj2 = null;
                    if (property != null)
                    {
                        obj2 = property.GetValue(event2, new object[0]);
                    }
                    if (i == 0)
                    {
                        item = new ListViewItem((obj2 != null) ? obj2.ToString() : string.Empty);
                    }
                    else
                    {
                        items[i - 1] = (obj2 != null) ? obj2.ToString() : string.Empty;
                    }
                }
                item.SubItems.AddRange(items);
                this.mListView.Items.Add(item);
            }
        }

        private void InitListView()
        {
            this.mListView.Columns.Clear();
            foreach (string str in this.mSetting.PropertyList)
            {
                this.mListView.Columns.Add(str, str);
            }
            foreach (ColumnHeader header in this.mListView.Columns)
            {
                header.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize);
            }
        }

        public void OnConnect(Server pServer)
        {
            this.OnDisconnect();
            this.mServer = pServer;
            this.SetState(eTracerState.Stopped);
            this.InitListView();
            this.OnStart();
        }

        public void OnDisconnect()
        {
            if (this.mServer != null)
            {
                this.OnStop();
                this.mServer.Disconnect(false);
                this.mServer = null;
                this.SetState(eTracerState.Disconnected);
            }
        }

        private void OnSettingChanged()
        {
            this.mListView.Items.Clear();
            this.InitListView();
        }

        public void OnStart()
        {
            this.SubscribeToSessionTrace();
            this.SetState(eTracerState.Running);
        }

        private void OnStateChaged()
        {
            if (this.StateChanged != null)
            {
                this.StateChanged(this, new EventArgs());
            }
        }

        public void OnStop()
        {
            this.UnsubscribeToSessionTrace();
            this.SetState(eTracerState.Stopped);
        }

        private void SessionTrace_OnEvent(object pSender, TraceEventArgs pArgs)
        {
            this.AddTraceToListView(pArgs);
        }

        private void SessionTrace_Stopped(ITrace pSender, TraceStoppedEventArgs pArgs)
        {
            if (pArgs.get_StopCause() == 2)
            {
                throw pArgs.get_Exception();
            }
        }

        private void SetState(eTracerState pState)
        {
            if (this.mState != pState)
            {
                this.mState = pState;
                this.OnStateChaged();
            }
        }

        private void SubscribeToSessionTrace()
        {
            this.mServer.get_SessionTrace().add_OnEvent(new TraceEventHandler(this, (IntPtr) this.SessionTrace_OnEvent));
            this.mServer.get_SessionTrace().add_Stopped(new TraceStoppedEventHandler(this, (IntPtr) this.SessionTrace_Stopped));
            this.mServer.get_SessionTrace().Start();
        }

        private void UnsubscribeToSessionTrace()
        {
            if ((this.mServer != null) && (this.mServer.get_SessionTrace() != null))
            {
                this.mServer.get_SessionTrace().remove_OnEvent(new TraceEventHandler(this, (IntPtr) this.SessionTrace_OnEvent));
                this.mServer.get_SessionTrace().remove_Stopped(new TraceStoppedEventHandler(this, (IntPtr) this.SessionTrace_Stopped));
                this.mServer.get_SessionTrace().Stop();
            }
        }

        public TracerSetting Setting
        {
            get
            {
                return this.mSetting;
            }
            set
            {
                this.mSetting = value;
                this.OnSettingChanged();
            }
        }

        public eTracerState State
        {
            get
            {
                return this.mState;
            }
        }

        private delegate void AddTraceToListViewDelegate(TraceEventArgs pArgs);
    }
}

